﻿using System;

namespace Birkelund.QueryStrings
{
    /// <summary>
    /// Common interface for strongly typed query string tokens
    /// </summary>
    /// <typeparam name="T">The type of the token</typeparam>
    public interface IQueryStringToken<T> : ITokenKey
    {
        #region Properties
        /// <summary>
        /// The value to return if any errors occurs or if null/no value is found
        /// </summary>
        T DefaultValue { get; }

        /// <summary>
        /// Delegate that is called if the token parser discovers an error. Is called before any exception is thrown. See ErrorNotificationBehaviour
        /// </summary>
        Action<FailureArgs> ReadFailureAction { get; set; }

        /// <summary>
        /// Gets or sets the ExceptionNotificationBehaviour.
        /// </summary>
        /// <value>The value to get or set.</value>
        ExceptionNotificationBehaviour ExceptionNotificationBehaviour { get; set; }

        /// <summary>
        /// Gets or sets the validator. If validation fails, the token parser will enter errormode and call <see cref="ReadFailureAction"/>
        /// </summary>
        /// <value>The validator.</value>
        Func<T, bool> Validator { get; set; }

        /// <summary>
        /// Get or sets the encryption algorithm. If null (default) encryption will not be used.
        /// </summary>
        ISymmetricEncryption EncryptionAlgorithm { get; set; }
        #endregion

        #region Methods
        /// <summary>
        /// Renders the token value
        /// </summary>
        /// <returns>Returns the rendered value. Intented to be used by the framswork internal</returns>
        string RenderTokenValue(T value);

        /// <summary>
        /// Reads the value from the specified querystring
        /// </summary>
        /// <param name="uri">The URI.</param>
        /// <param name="readmode">The readmode to apply</param>
        /// <returns>
        /// Returns the read value.
        /// If the value cannot be passed to currentType T or if the value doesn't exist the default value will be returned.
        /// </returns>
        T ReadValue(Uri uri, ReadValueMode readmode);

        /// <summary>
        /// Tries to read the value.
        /// </summary>
        /// <param name="uri">The uri.</param>
        /// <param name="result">The result.</param>
        /// <param name="readmode">The readmode to apply. See UriWriter.ApplyCheckSum</param>
        /// <returns>True or false</returns>
        bool TryReadValue(Uri uri, out T result, ReadValueMode readmode);

        /// <summary>
        /// Reads the value from the current querystring
        /// </summary>
        /// <returns>
        /// Returns the read value.
        /// If the value cannot be passed to currentType T or if the value doesn't exist the default value will be returned.
        /// </returns>
        T ReadValue();

        /// <summary>
        /// Reads the value from the current querystring
        /// </summary>
        /// <param name="readmode">The readmode to apply. See IUriWriter.ApplyCheckSum</param>
        /// <returns>
        /// Returns the read value.
        /// If the value cannot be passed to currentType T or if the value doesn't exist the default value will be returned.
        /// </returns>
        T ReadValue(ReadValueMode readmode);

        /// <summary>
        /// Reads the value from the specified querystring
        /// </summary>
        /// <param name="uri">The uri to determine</param>
        /// <returns>
        /// Returns the read value.
        /// If the value cannot be passed to currentType T or if the value doesn't exist the default value will be returned.
        /// </returns>
        T ReadValue(Uri uri);

        /// <summary>
        /// Tries to read the value./>
        /// </summary>
        /// <param name="result">The result.</param>
        /// <returns>True or false</returns>
        bool TryReadValue(out T result);

        /// <summary>
        /// Tries to read the value.
        /// </summary>
        /// <param name="result">The result.</param>
        /// <param name="readmode">The readmode to apply. See UrlWriter.ApplyCheckSum</param>
        /// <returns>True or false</returns>
        bool TryReadValue(out T result, ReadValueMode readmode);

        /// <summary>
        /// Checks whether the current token exists in the current QueryString
        /// </summary>
        /// <returns>True or false</returns>
        bool Exists();

        /// <summary>
        /// Checks whether the current token exists in the specified url
        /// </summary>
        /// <param name="url">The url to determine</param>
        /// <returns>True or false</returns>
        bool Exists(Uri url);
        #endregion
    }
}